package com.piggy.logi.sys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.logi.sys.api.vo.LogiLineExtVo;
import com.piggy.logi.sys.api.vo.LogiLineStationVo;
import com.piggy.logi.sys.api.vo.LogiLineVo;
import com.piggy.logi.sys.api.vo.LogiSysDeptExtVo;
import com.piggy.logi.sys.bo.LogiLineQueryBo;
import com.piggy.logi.sys.bo.LogiLineStationEditBo;
import com.piggy.logi.sys.bo.LogiLineStationQueryBo;
import com.piggy.logi.sys.domain.LogiLine;
import com.piggy.logi.sys.domain.LogiLineStation;
import com.piggy.logi.sys.enums.StationFlagEnum;
import com.piggy.logi.sys.mapper.LogiLineStationMapper;
import com.piggy.logi.sys.service.ILogiLineService;
import com.piggy.logi.sys.service.ILogiLineStationService;
import com.piggy.logi.sys.service.ILogiSysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 项目管理Service业务层处理
 *
 * @author piggy
 * @date 2023-08-14
 */
@Slf4j
@Service
public class LogiLineStationServiceImpl extends ServiceImpl<LogiLineStationMapper, LogiLineStation> implements ILogiLineStationService {

    @Resource
    private ILogiLineService lineService;

    @Resource
    private ILogiSysDeptService deptService;

    @Override
    public LogiLineStationVo queryById(Long id) {
        return getVoById(id, LogiLineStationVo.class);
    }

    @Override
    public TableDataInfo<LogiLineStationVo> queryPageList(LogiLineStationQueryBo bo) {
        PagePlus<LogiLineStation, LogiLineStationVo> result = pageVo(PageUtils.buildPagePlus(bo, true), buildQueryWrapper(bo), LogiLineStationVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<LogiLineStationVo> queryList(LogiLineStationQueryBo bo) {
        return listVo(buildQueryWrapper(bo), LogiLineStationVo.class);
    }

    private LambdaQueryWrapper<LogiLineStation> buildQueryWrapper(LogiLineStationQueryBo bo) {
        LambdaQueryWrapper<LogiLineStation> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, LogiLineStation::getId, bo.getId());
        lqw.eq(bo.getLineId() != null, LogiLineStation::getLineId, bo.getLineId());
        lqw.eq(StrUtil.isNotBlank(bo.getStationFlag()), LogiLineStation::getStationFlag, bo.getStationFlag());
        lqw.eq(bo.getBranchDeptId() != null, LogiLineStation::getBranchDeptId, bo.getBranchDeptId());
        lqw.eq(bo.getBranchUserId() != null, LogiLineStation::getBranchUserId, bo.getBranchUserId());
        lqw.eq(bo.getStationMile() != null, LogiLineStation::getStationMile, bo.getStationMile());
        lqw.eq(bo.getStationTime() != null, LogiLineStation::getStationTime, bo.getStationTime());
        lqw.eq(bo.getDispatchDistance() != null, LogiLineStation::getDispatchDistance, bo.getDispatchDistance());
        lqw.eq(bo.getSort() != null, LogiLineStation::getSort, bo.getSort());
        lqw.eq(StrUtil.isNotBlank(bo.getStatus()), LogiLineStation::getStatus, bo.getStatus());
        return lqw;
    }

    @Override
    public Boolean addByAddBo(LogiLineStationEditBo bo) {
        LogiLineStation add = BeanUtil.toBean(bo, LogiLineStation.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(LogiLineStationEditBo bo) {
        LogiLineStation update = BeanUtil.toBean(bo, LogiLineStation.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByAddBo(List<LogiLineStationEditBo> boList) {
        if (CollUtil.isNotEmpty(boList)) {
            this.remove(Wrappers.<LogiLineStation>lambdaQuery().eq(LogiLineStation::getLineId, boList.get(0).getLineId()));
            return this.saveBatch(BeanUtil.copyToList(boList, LogiLineStation.class));
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchByUpdateBo(List<LogiLineStationEditBo> boList) {
        if (CollUtil.isNotEmpty(boList)) {
            this.remove(Wrappers.<LogiLineStation>lambdaQuery().eq(LogiLineStation::getLineId, boList.get(0).getLineId()));
            return this.saveOrUpdateBatch(BeanUtil.copyToList(boList, LogiLineStation.class));
        }
        return false;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(LogiLineStation entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }

    @Override
    public List<LogiLineExtVo> selectGeoDeptList(BigDecimal lng, BigDecimal lat) {

        LambdaQueryWrapper<LogiLine> queryWrapper = lineService.buildQueryWrapper((LogiLineQueryBo) new LogiLineQueryBo().setDeptId(SecurityUtils.getDeptId()));
        List<LogiLineExtVo> lineList = lineService.listVo(queryWrapper, LogiLineExtVo.class);
        if (CollUtil.isEmpty(lineList)) {
            return lineList;
        }
        List<Long> lineIds = lineList.stream().map(LogiLineVo::getLineId).collect(Collectors.toList());
        Map<Long, LogiLineExtVo> lineMap = lineList.stream().collect(Collectors.toMap(LogiLineExtVo::getLineId, Function.identity()));

        LambdaQueryWrapper<LogiLineStation> lqw = Wrappers.lambdaQuery();
        lqw.in(LogiLineStation::getLineId, lineIds).ne(LogiLineStation::getStationFlag, StationFlagEnum.END.getCode());
        List<LogiLineStation> lineStationList = this.list(lqw);
        if (CollUtil.isEmpty(lineStationList)) {
            return lineList;
        }

        Map<Long, List<Long>> deptLineMap = lineStationList.stream().collect(HashMap::new, (m, v) -> {
            if (!m.containsKey(v.getBranchDeptId())) {
                m.put(v.getBranchDeptId(), new ArrayList<>());
            }
            m.get(v.getBranchDeptId()).add(v.getLineId());
        }, HashMap::putAll);

        List<Long> deptIds = lineStationList.stream().distinct().map(LogiLineStation::getBranchDeptId).collect(Collectors.toList());
        List<LogiSysDeptExtVo> deptVos = deptService.selectGeoLineDeptList(deptIds, lng, lat);
        if (CollUtil.isEmpty(deptVos)) {
            return lineList;
        }
        lineList.clear();

        deptVos.forEach(Any-> {
            List<Long> lineIds1 = deptLineMap.get(Any.getDeptId());
            if (CollUtil.isEmpty(lineIds1)) {
                return ;
            }
            lineIds1.forEach(t-> {
                if (lineMap.containsKey(t)) {
                    lineMap.get(t).setDistince(Any.getDistince());
                    lineList.add(lineMap.get(t));
                    lineMap.remove(t);
                }
            });
        });

        return lineList;
    }

}
